package com.ballmaze.maze;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

@Slf4j
public class MazeMap {
    MazeUnit[][] mazeMap;
    int width;
    int height;
    public static final char TYPE_EMPTY_OUTSIDE = '~';
    public static final char TYPE_EMPTY_INSIDE = '.';
    public static final char TYPE_PLAYER = 'p';
    public static final char TYPE_FOOD = '$';
    public static final char TYPE_OBSTACLE = '#';
    public MazeLocation[] obstacles;
    //碰撞序列 如果有两个用户以上存在于同一个格子之中 那么会触发
    private HashMap<String, MazeUnit> collisionMap;

    public MazeMap(int width, int height) {
        mazeMap = new MazeUnit[height][width];
        LinkedList<MazeLocation> obstaclesList = new LinkedList<>();
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                MazeUnit unit = new MazeUnit(MapCreate.createUnit());
                mazeMap[i][j] = unit;
                if (unit.type == MazeUnitType.TYPE_OBSTACLE) {
                    obstaclesList.add(new MazeLocation(i, j));
                }
            }
        }
        obstacles = new MazeLocation[obstaclesList.size()];
        collisionMap = new HashMap<>();
        int cursor = 0;
        for (MazeLocation mazeLocation : obstaclesList) {
            obstacles[cursor++] = mazeLocation;
        }
        this.width = width;
        this.height = height;
    }

    public boolean checkAvailable(int y, int x) {
        //越界
        if (!borderCheck(y, x)) return false;
        //如果新的单元格不合格
        if (mazeMap[y][x].getType() == MazeUnitType.TYPE_OBSTACLE) {
            return false;
        }
        return true;
    }

    private boolean borderCheck(int y, int x) {
        if (x < 0 || x >= width || y < 0 || y >= height) {
            return false;
        }
        return true;
    }

    public char[][] copyMazeMap() {
        char[][] buffer = new char[height][width];
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                buffer[i][j] = mazeMap[i][j].toChar();
            }
        }
        return buffer;
    }

    public char getValue(int y, int x) {
        if (!borderCheck(x, y)) {
            return TYPE_EMPTY_OUTSIDE;
        }
        return mazeMap[y][x].toChar();
    }

    public MazeLocation[] getObstacles() {
        return obstacles;
    }

    public void insertPlayer(Player player) {
        mazeMap[player.getY()][player.getX()].playerJoin(player);
    }

    public void movePlayer(Player player, int oldY, int oldX, int newY, int newX) throws MazeException {
        boolean flag = mazeMap[oldY][oldX].playerLeave(player);
        if (!flag) {
            throw new MazeException("老地方不存在用户");
        }
        mazeMap[newY][newX].playerJoin(player);
    }

    public void removePlayer(Player deadPlayer) throws MazeException {
        boolean leaveSuccess = mazeMap[deadPlayer.getY()][deadPlayer.getX()].playerLeave(deadPlayer);
        if (!leaveSuccess) {
            throw new MazeException("在MazeMap中移除用户失败");
        }
    }

    enum MazeUnitType {
        TYPE_EMPTY,
        TYPE_OBSTACLE
    }

    public class MazeUnit {
        MazeUnitType type;
        ArrayList<Player> players;
        Food food;

        public MazeUnit(MazeUnitType type) {
            this.type = type;
            this.players = new ArrayList<>(4);
        }

        public void playerJoin(Player player) {
            this.players.add(player);
        }

        public boolean playerLeave(Player player) {
            return this.players.remove(player);
        }

        public Food foodLeave() {
            Food food = this.food;
            this.food = null;
            return food;
        }

        public void foodJoin(Food food) {
            this.food = food;
        }

        public MazeUnitType getType() {
            return type;
        }

        public char toChar() {
            if (type == MazeUnitType.TYPE_OBSTACLE)
                return TYPE_OBSTACLE;
            else if (type == MazeUnitType.TYPE_EMPTY) {
                if (players.size() != 0) {
                    char c = (char) ((int) players.get(0).getPower() + '0');
                    return c;
                } else if (food != null) {
                    return TYPE_FOOD;
                } else {
                    return TYPE_EMPTY_INSIDE;
                }
            } else {
                return TYPE_EMPTY_OUTSIDE;
            }
        }
    }

    private static class MapCreate {

        private static double obstacleGenerateRates = 0.05;

        public static MazeUnitType createUnit() {
            if (Math.random() < obstacleGenerateRates)
                return MazeUnitType.TYPE_OBSTACLE;
            else
                return MazeUnitType.TYPE_EMPTY;
        }
    }

    public static void main(String[] args) {
        float a = 2.7f;
        char c = (char) ((int) a + '0');
        System.out.println(c);
    }
}
